package com.myk.game.gobangchess.rooms;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.myk.game.gobangchess.*;
import com.myk.game.gobangchess.constants.AppConfig;
import com.myk.game.gobangchess.constants.BoardStyleData;
import com.myk.game.gobangchess.constants.Msger;
import com.myk.game.gobangchess.constants.PathCost;
import com.myk.game.gobangchess.utils.FileUtils;
import com.myk.game.gobangchess.utils.GridsUtils;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

/**
 * 无规则画板
 */
public class NoRuleRoom extends Room {

    int[] blackPlayerLastPoint;
    int[] whitePlayerLastPoint;
    List<int[][]> savedGridsList; //缓存的布局
    int restoreIndex = 0; //当前还原到的缓存索引

    int cusBtnMode = 0; //按钮管理模式， 0：布局管理    1：棋盘管理
    boolean isBigArrow = true; // true：扩大模式   false：缩小模式

    long lastSavedTime = System.currentTimeMillis(); //上次保存的时间

    String roomDataPath = PathCost.ROOM_DATA_DIR + NoRuleRoom.class.getSimpleName() + "/";
    String gridCacheFile = roomDataPath + "gridCache.txt";

    CustomBottom cb_resetGrids = new CustomBottom(this, "一键清空", (player) -> {
        int curRow = curGrids.length;
        int curCol = curGrids[0].length;
        curGrids = GridsUtils.createEmptyGrids(curRow, curCol);
        noticeAllRefreshGameInfo();
        noticeAllBroadcast("当前布局被清空");
    });

    CustomBottom cb_saveGrids = new CustomBottom(this, "保存布局", (player) -> {
        long curTime = System.currentTimeMillis();
        if (curTime - lastSavedTime < 1000) {
            lastSavedTime = System.currentTimeMillis();
            return;  //频繁触发不进行保存！！！
        }

        if (savedGridsList == null) {
            savedGridsList = new ArrayList<>();
        }
        savedGridsList.add(GridsUtils.copyGrids(curGrids)); //缓存到内存中
        if (savedGridsList.size() > Integer.parseInt(AppConfig.no_rule_room_cache_count)) { //超过上限移除第一条
            savedGridsList.remove(0);
        }
        restoreIndex = savedGridsList.size() - 1;

        if (savedGridsList.size() > 0) { //这边肯定会大于0啊
            FileUtils.createOrExistsDir(roomDataPath);
            FileUtils.writeFileFromString(gridCacheFile, new Gson().toJson(savedGridsList));  //缓存到本地
            noticeAllBroadcast("当前布局已被保存");
            lastSavedTime = System.currentTimeMillis();
        }
    });

    CustomBottom cb_restoreGrids = new CustomBottom(this, "还原布局", (player) -> {
        if (savedGridsList != null && savedGridsList.size() > 0) {
            curGrids = savedGridsList.get(restoreIndex);
            noticeAllRefreshGameInfo();
            noticeAllBroadcast("还原到之前保存的布局");
            restoreIndex--;
            if (restoreIndex < 0) {
                restoreIndex = savedGridsList.size() - 1;
            }
        }
        else {
            noticeAllBroadcast("缓存中无数据");
        }
    });

    CustomBottom cb_changeRow = new CustomBottom(this, "修改行", (player) -> {
        int curRow = curGrids.length;
        int curCol = curGrids[0].length;
        if (isBigArrow) { //增加模式
            if (curRow >= 99) { //设置行的上限
                noticeAllBroadcast("棋盘行数已最大");
            }
            else {
                int newRow = curRow + 1;
                int[][] newGrids = GridsUtils.createEmptyGrids(newRow, curCol);
                GridsUtils.fillGrids(curGrids, newGrids);
                curGrids = newGrids;
            }
        }
        else { //减少模式
            if (curRow == 1) { //设置行的下限
                noticeAllBroadcast("棋盘行数已最小");
            }
            else {
                int newRow = curRow - 1;
                int[][] newGrids = GridsUtils.createEmptyGrids(newRow, curCol);
                GridsUtils.fillGrids(curGrids, newGrids);
                curGrids = newGrids;
            }
        }
        noticeAllRefreshGameInfo(); //修改了棋盘大小此时就要通知界面刷新了
    });

    CustomBottom cb_changeCol = new CustomBottom(this, "修改列", (player) -> {
        int curRow = curGrids.length;
        int curCol = curGrids[0].length;
        if (isBigArrow) { //增加模式
            if (curCol >= 99) { //设置列的上限
                noticeAllBroadcast("棋盘列数已最大");
            }
            else {
                int newCol = curCol + 1;
                int[][] newGrids = GridsUtils.createEmptyGrids(curRow, newCol);
                GridsUtils.fillGrids(curGrids, newGrids);
                curGrids = newGrids;
            }
        }
        else { //减少模式
            if (curCol == 1) { //设置列的下限
                noticeAllBroadcast("棋盘列数已最小");
            }
            else {
                int newCol = curCol - 1;
                int[][] newGrids = GridsUtils.createEmptyGrids(curRow, newCol);
                GridsUtils.fillGrids(curGrids, newGrids);
                curGrids = newGrids;
            }
        }
        noticeAllRefreshGameInfo();
    });

    CustomBottom cb_changeArrow = new CustomBottom(this, "修改方向", (player) -> {
        isBigArrow = !isBigArrow;
        refreshCusBottoms();
    });

    CustomBottom cb_changeMode = new CustomBottom(this, "切换模式", (player) -> {
        if (cusBtnMode == 0) {
            cusBtnMode = 1;
        }
        else if (cusBtnMode == 1) {
            cusBtnMode = 0;
        }
        refreshCusBottoms();
    });


    public NoRuleRoom(String roomName) {
        super(roomName, "\t\t可以自由的摆放棋子、管理布局、修改棋盘，没有具体的规则。", "无规则画板", BoardStyleData.getGoBangStyle(9, 9), false, false);
        setSortingBottomValue(true); //无规则画板永远置底
        initGridListCache();
    }

    private void initGridListCache() {
        if (FileUtils.isFileExists(gridCacheFile)) {
            String cachedData = FileUtils.readFile2String(gridCacheFile);
            if (cachedData != null && !cachedData.isEmpty()) {
                try {
                    Type type = new TypeToken<ArrayList<int[][]>>() {
                    }.getType();
                    savedGridsList = new Gson().fromJson(cachedData, type);
                }
                catch (Exception e) {
                    System.out.println("无规则画板加载布局缓存出错：" + e);
                }
            }
        }
    }

    @Override
    public String getRuleText() {
        return "可以自由的摆放棋子、管理布局、修改棋盘，没有具体的规则。\n点击落座后一个人也能开始布局。\n注意下方的自定义按钮”切换模式“可以切换按钮菜单。";
    }

    @Override
    public void checkGameStart() {
        notice(); //只要有棋手就都能落子，不需要双方就位
        refreshCusBottoms(); //分发自定义按钮
    }

    @Override
    public void playerReConnectEnter(Player player) {
        super.playerReConnectEnter(player);
        if (player == player_black || player == player_white){
            notice(); //只要有棋手就都能落子，不需要双方就位
            refreshCusBottoms(); //分发自定义按钮
        }
    }

    //刷新最新的自定义按钮组
    private void refreshCusBottoms()  {
        if (cusBtnMode == 0) {  //管理布局模式
            if (player_black != null) {
                player_black.clearCustomBottom(); //一定要先清空
                player_black.registerCustomBottom(cb_resetGrids, cb_saveGrids, cb_restoreGrids, cb_changeMode);
            }
            if (player_white != null) {
                player_white.clearCustomBottom();//一定要先清空
                player_white.registerCustomBottom(cb_resetGrids, cb_saveGrids, cb_restoreGrids, cb_changeMode);
            }
        }
        else if (cusBtnMode == 1) { //修改棋盘模式
            if (isBigArrow) { //修改方向为扩大
                cb_changeRow.setTitle("增加一行");
                cb_changeCol.setTitle("增加一列");
            }
            else { //修改方向为缩小
                cb_changeRow.setTitle("减小一行");
                cb_changeCol.setTitle("减小一列");
            }
            if (player_black != null) {
                player_black.clearCustomBottom();//一定要先清空
                player_black.registerCustomBottom(cb_changeRow, cb_changeCol, cb_changeArrow, cb_changeMode);
            }
            if (player_white != null) {
                player_white.clearCustomBottom();//一定要先清空
                player_white.registerCustomBottom(cb_changeRow, cb_changeCol, cb_changeArrow, cb_changeMode);
            }
        }
    }

    @Override
    public void resetGrids() {
        step = 0;
        gameTip = "-1";
        //super.resetGrids(); //永远不清空棋盘
        blackPlayerLastPoint = null;
        whitePlayerLastPoint = null;
    }

    @Override
    public void moveLater(Player player, int row, int col) {
        //没有回合概念，不需要轮换，双方一直都可以轮流落子。
        if (player_black == player) {
            doRule(row, col, 1);
        }
        if (player_white == player) {
            doRule(row, col, 2);
        }
    }

    @Override
    public void doRule(int row, int col, int value) {
        if (value == 1) {
            int bValue = value; //黑方默认落下黑棋
            if (blackPlayerLastPoint != null && row == blackPlayerLastPoint[0] && col == blackPlayerLastPoint[1]) { //黑方落子位置和上一次一样
                bValue = blackChangeValue(blackPlayerLastPoint[2]); //连点切换机制
            }
            else if (curGrids[row][col] != 0) {
                bValue = 0; //首次落在非空的位置置空
            }
            blackPlayerLastPoint = new int[]{row, col, bValue}; //记录黑方上一步落子
            curGrids[row][col] = bValue; //显示落子
            stepAdd();
        }
        else if (value == 2) {
            int wValue = value; //白方默认落下白棋
            if (whitePlayerLastPoint != null && row == whitePlayerLastPoint[0] && col == whitePlayerLastPoint[1]) { //白方落子位置和上一次一样
                wValue = whiteChangeValue(whitePlayerLastPoint[2]); //连点切换机制
            }
            else if (curGrids[row][col] != 0) {
                wValue = 0; //首次落在非空的位置置空
            }
            whitePlayerLastPoint = new int[]{row, col, wValue}; //记录白方上一步落子
            curGrids[row][col] = wValue; //显示落子
            stepAdd();
        }
        notice(); //走完后要刷新一下，没有获胜规则
    }

    private int blackChangeValue(int i) {
        if (i == 1) {
            return 2;
        }
        else if (i == 2) {
            return 9;
        }
        else if (i == 9) {
            return 3;
        }
        else if (i == 3) {
            return 4;
        }
        else if (i == 4) {
            return 5;
        }
        else if (i == 5) {
            return 6;
        }
        else if (i == 6) {
            return 7;
        }
        else if (i == 7) {
            return 11;
        }
        else if (i == 11) {
            return 12;
        }
        else if (i == 12) {
            return 13;
        }
        else if (i == 13) {
            return 14;
        }
        else if (i == 14) {
            return 15;
        }
        else if (i == 15) {
            return 16;
        }
        else if (i == 16) {
            return 17;
        }
        else if (i == 17) {
            return 8;
        }
        else if (i == 8) {
            return 0;
        }
        else if (i == 0) {
            return 1;
        }
        return i;
    }

    private int whiteChangeValue(int i) {
        if (i == 2) {
            return 1;
        }
        else if (i == 1) {
            return 9;
        }
        else if (i == 9) {
            return 3;
        }
        else if (i == 3) {
            return 4;
        }
        else if (i == 4) {
            return 5;
        }
        else if (i == 5) {
            return 6;
        }
        else if (i == 6) {
            return 7;
        }
        else if (i == 7) {
            return 11;
        }
        else if (i == 11) {
            return 12;
        }
        else if (i == 12) {
            return 13;
        }
        else if (i == 13) {
            return 14;
        }
        else if (i == 14) {
            return 15;
        }
        else if (i == 15) {
            return 16;
        }
        else if (i == 16) {
            return 17;
        }
        else if (i == 17) {
            return 8;
        }
        else if (i == 8) {
            return 0;
        }
        else if (i == 0) {
            return 2;
        }
        return i;
    }

    private void notice() {
        if (player_black != null && player_white != null) {
            noticeAllMove();
        }
        else if (player_black != null) {
            noticeBlackMove();
        }
        else if (player_white != null) {
            noticeWhiteMove();
        }
        else {
            noticeNoMove();
        }
    }

    @Override
    public int getCountdownSec() {
        return Integer.parseInt(AppConfig.player_countdown_sec_1side); //无规则画板落子计时时间比一般房间长
    }

    /**
     * 通知房间内所有人更新倒计时开始时间(单位：秒)（负数的话不显示倒计时）
     * 开启倒计时业务超时了就将超时的用户踢出去，代码调用玩家的离开方法
     */
    @Override
    protected void noticeAllCountdown(int blackCountdown, int whiteCountdown) {
        /*无规则画板单人也能行棋，所以也会有倒计时*/
        blackCountdown = player_black == null ? -1 : getCountdownSec();
        whiteCountdown = player_white == null ? -1 : getCountdownSec();
        super.noticeAllCountdown(blackCountdown, whiteCountdown);
    }

    /**
     * 通知指定用户刷新当前倒计时动画
     */
    @Override
    protected void noticePlayerCurrentCountDown(Player player) {
        int blackRemainingSec = blackCountdownOverTimer != null ? blackCountdownOverTimer.getRemainingSec() : -1;
        int whiteRemainingSec = whiteCountdownOverTimer != null ? whiteCountdownOverTimer.getRemainingSec() : -1;
        /*无规则画板单人也能行棋，所以也会有倒计时*/
        blackRemainingSec = player_black == null ? -1 : blackRemainingSec;
        whiteRemainingSec = player_white == null ? -1 : whiteRemainingSec;
        player.sendMessage(Msger.refreshCountdown, blackRemainingSec + "&" + whiteRemainingSec);
    }
}
